package org.softmed.rest.server.core.guice;

import java.util.List;
import org.restlet.data.Protocol;
import org.softmed.rest.server.core.boot.BootupProcessor;
import org.softmed.rest.server.core.boot.Startup;
import org.softmed.rest.server.core.handler.DefaultHandlerProcessor;
import org.softmed.rest.server.core.handler.DefaultHandlerProvider;
import org.softmed.rest.server.core.handler.HandlerProcessor;
import org.softmed.rest.server.core.handler.SpecificHandlerSolver;
import org.softmed.rest.server.core.handler.impls.JavaSolver;
import org.softmed.rest.server.core.http.DefaultHttpMethodProcessor;
import org.softmed.rest.server.core.http.HttpMethodProcessor;
import org.softmed.rest.server.core.http.SpecificHttpMethodProcessor;
import org.softmed.rest.server.core.http.SpecificMethodProcessorProvider;
import org.softmed.rest.server.core.http.specific.DeleteProcessor;
import org.softmed.rest.server.core.http.specific.GetProcessor;
import org.softmed.rest.server.core.http.specific.PostProcessor;
import org.softmed.rest.server.core.http.specific.PutProcessor;
import org.softmed.rest.server.core.restlet.RESTConfigRefresher;
import org.softmed.rest.server.core.restlet.RESTServer;
import org.softmed.rest.server.core.restlet.ResourceHandler;

import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;

public class CoreRESTServerModule implements Module {

	private int port;
	private String path;
	private String domain;
	private boolean setupDefaultHandlerSolution;
	private RESTServer server;

	String storedRESTContextName = "stored-rest";

	public CoreRESTServerModule(int port, String path, String domain,
			boolean setupHandlerSolution) {
		this.port = port;
		this.path = path;
		this.domain = domain;
		this.setupDefaultHandlerSolution = setupHandlerSolution;
	}

	@Override
	public void configure(Binder binder) {

		try {

			if (setupDefaultHandlerSolution) {
				binder.bind(SpecificHandlerSolver.class).annotatedWith(
						new NamedAnnotation("JavaSolver")).to(JavaSolver.class);

				binder.bind(new TypeLiteral<List<SpecificHandlerSolver>>() {
				}).toProvider(DefaultHandlerProvider.class);
			}

			
			binder.bind(HandlerProcessor.class).to(DefaultHandlerProcessor.class)
			.asEagerSingleton();
			
			binder.bind(SpecificHttpMethodProcessor.class).annotatedWith(
					new NamedAnnotation("GetProcessor")).to(GetProcessor.class);
			binder.bind(SpecificHttpMethodProcessor.class).annotatedWith(
					new NamedAnnotation("PostProcessor")).to(
					PostProcessor.class);
			binder.bind(SpecificHttpMethodProcessor.class).annotatedWith(
					new NamedAnnotation("PutProcessor")).to(PutProcessor.class);
			binder.bind(SpecificHttpMethodProcessor.class).annotatedWith(
					new NamedAnnotation("DeleteProcessor")).to(
					DeleteProcessor.class);

			binder.bind(new TypeLiteral<List<SpecificHttpMethodProcessor>>() {
			}).toProvider(SpecificMethodProcessorProvider.class)
					.asEagerSingleton();

			binder.bind(HttpMethodProcessor.class).to(
					DefaultHttpMethodProcessor.class).asEagerSingleton();

			binder.requestStaticInjection(ResourceHandler.class);

			server = new RESTServer(Protocol.HTTP, port, path, domain);
			binder.bind(RESTServer.class).toInstance(server);

			binder.bindConstant().annotatedWith(
					new NamedAnnotation("StoredRESTContextName")).to(
					storedRESTContextName);

			binder.bindConstant().annotatedWith(new NamedAnnotation("bootDir"))
					.to("bootup");

			binder.requestStaticInjection(RESTConfigRefresher.class);
			
			binder.requestStaticInjection(Startup.class);

		} catch (Throwable t) {
			t.printStackTrace();
			System.exit(1);
		}
	}

	public RESTServer getServer() {
		return server;
	}

	public void setServer(RESTServer server) {
		this.server = server;
	}

	public String getStoredRESTContextName() {
		return storedRESTContextName;
	}

	public void setStoredRESTContextName(String storedRESTContextName) {
		this.storedRESTContextName = storedRESTContextName;
	}

}
